import { PropMethod, PropType } from '@vue/runtime-core'

/* eslint-disable */
type NormalizeType<T> = T extends StringConstructor ? string : T extends NumberConstructor ? number : T extends BooleanConstructor ? boolean : T;
// 定义Prop类型
type BuiltInType<T> = StringConstructor | NumberConstructor | BooleanConstructor | T;
// 定义createCompenent函数接受的prop类型

type StandardPropType<T> = {type: BuiltInType<T>; require?: boolean}
/**
 * prop的属性类型 有可能是字符串、数值 boolean
 * 也有可能是对象，标准的type加require
 */
type DefaultType<T = {}> = {
  [key: string]: {type: BuiltInType<T>; require?: boolean} | BuiltInType<T>;
}

/**
 * 使用infer表示占位
 * 解构？
 * 难度5颗星
 * 如果是标准的type+require 返回类型取type,
 * 如果是{type} 返回类型取type
 * 如果直接是类型则直接转换
 */
type ReflexType<T> = {
  [key in keyof T]: T[key] extends { type: infer TYPE; require: true } ? NormalizeType<TYPE> | 'first'
    : T[key] extends { type: infer TYPE } ? NormalizeType<TYPE> | 'nakura': NormalizeType<T[key]> | 'string'
}

declare function createComponent<T extends DefaultType> (options: {
  props: T;
  // props 的具体类型从T里取，T的类型由用户基于DefaultType确定
  // 难点在于怎么从T中映射到props
  setup (props: ReflexType<T>): any;
}): {}

interface TT {
  flag: boolean;
}

const t:TT = {
  flag: false
}

createComponent({
  props: {
    str: String,
    wait: {
      type:Number
    },
    name: {
      type: String,
      require:false
    }
  },
  setup (props) {
    props.str
    props.wait
    props.name
  }
})

// export declare function defineComponent<PropsOptions extends Readonly<ComponentPropsOptions>, RawBindings, D, C extends ComputedOptions = {}, M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record<string, any>, EE extends string = string>(options: ComponentOptionsWithObjectProps<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>;
